package com.kos.matchingsystem.service.impl.utils;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;

@Component
public class MatchingPool extends Thread{

    private static List<Player> players = new LinkedList<>();
    private final ReentrantLock lock = new ReentrantLock();

    private static final String startGameUrl = "http://127.0.0.1:8090/pk/start/game";

    private static RestTemplate restTemplate;
    @Autowired
    public void setRestTemplate(RestTemplate restTemplate){
        MatchingPool.restTemplate = restTemplate;
    }

    public void addPlayer(Integer userId, Integer rating, Integer snakeId){
        lock.lock();
        try{
            players.add(new Player(userId,rating,snakeId,0));
        } finally {
            lock.unlock();
        }
    }

    public void removePlayer(Integer userId){
        lock.lock();
        try{
            List<Player> newPlayers = new LinkedList<>();
            for(Player player : players){
                if(!player.getUserId().equals(userId)){
                    newPlayers.add(player);
                }
            }
            players = newPlayers;
        } finally {
            lock.unlock();
        }
    }

    //将所有当前玩家的等待时间加1
    private void increaseWaitingTime(){
        for(Player player : players){
            player.setWaitingTime(player.getWaitingTime() + 1);
        }
    }

    //判断两个玩家是否匹配
    private boolean checkMatched(Player a, Player b){
        int ratingDelta = Math.abs(a.getRating() - b.getRating());
        int waitingTime = Math.min(a.getWaitingTime(),b.getWaitingTime());
        return ratingDelta <= waitingTime * 10;
    }

    //返回a和b的匹配结果
    private void sendResult(Player a, Player b){
        System.out.println("send result:" + a + " " + b);
        MultiValueMap<String,String> data = new LinkedMultiValueMap<>();
        data.add("a_id",a.getUserId().toString());
        data.add("a_snake_id",a.getSnakeId().toString());
        data.add("b_id",b.getUserId().toString());
        data.add("b_snake_id",b.getSnakeId().toString());
        restTemplate.postForObject(startGameUrl,data,String.class);
    }

    //尝试匹配所有玩家
    private void matchPlayers(){
        System.out.println("match players:" + players.toString());
        boolean[] used = new boolean[players.size()];
        for(int i = 0; i < players.size(); i ++){
            if(used[i]){
                continue;
            }
            for(int j = i + 1; j < players.size(); j ++){
                if(used[i]){
                    continue;
                }
                Player a = players.get(i);
                Player b = players.get(j);
                if(checkMatched(a,b)){
                    used[i] = used[j] = true;
                    sendResult(a,b);
                    break;
                }
            }
        }
        List<Player> newPlayers = new LinkedList<>();
        for(int i = 0; i < players.size(); i++){
            if(!used[i]){
                newPlayers.add(players.get(i));
            }
        }
        players = newPlayers;
    }



    @Override
    public void run() {
        while(true){
            try {
                Thread.sleep(1000);
                lock.lock();
                try{
                    increaseWaitingTime();
                    matchPlayers();
                } finally {
                    lock.unlock();
                }

            } catch (InterruptedException e) {
                e.printStackTrace();
                break;
            }
        }
    }
}
